package org.jppf.application.template;

import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import org.jppf.application.template.Colorator.Palette;

public class GenFractal {

	public static List<FractalConfig> genConfigs() {

		int w = 1920;
		int h = 1080;
		int iter = 6000;
		int zoomLevel = 3000;
		
		double zoomPointX = -1.2341722881209505;
		double zoomPointY = -0.31631450224633023;
		
		double zf = 1.011;
		
		int halfw = w / 2;
		int halfh = h / 2;

		double sx = (h/2);
		double sy = (h/2);
		double tx = halfw - (zoomPointX * sx);
		double ty = ((zoomPointY * sy) + halfh);
		
		List<FractalConfig> ret = new ArrayList<FractalConfig>();
		
		for(int i = 0; i < zoomLevel; i++) {

			double x = (tx - halfw) / sx;
			sx *= zf;
			tx = ((x * sx) + halfw);
			
			double y = (ty - halfh) / sy;
			sy *= zf;
			ty = ((y * sy) + halfh);
			
			iter = (int)(Math.sqrt(Math.sqrt(sx)) + 200);
			FractalConfig config = new FractalConfig();
			config.id = String.valueOf(i + 1);
			config.w = w;
			config.h = h;
			config.sx = sx;
			config.sy = sy;
			config.tx = tx;
			config.ty = ty;
			config.iter = iter;
			ret.add(config);
			//System.out.println((i + 1) + "\t" + w + "\t" + h + "\t" + sx + "\t" + sy + "\t" + tx + "\t" + ty + "\t" + iter);
		}
		return ret;
	}
	
	public static BufferedImage generateFractal(FractalConfig config) {

		int w = config.w;
		int h = config.h;
		
		BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_BGR);
		
		
		Graphics2D g = bi.createGraphics();

		double sx = config.sx;
		double sy = config.sy;
		double tx = config.tx;
		double ty = config.ty;
		
		FractalFunctionParameters params = new FractalFunctionParameters();
		params.maxIter = config.iter;
		
		FractalFunction f = new Mandelbrot(params);
		Colorator co = new Colorator(Palette.RAINBOW);
		
		for(int i = 0; i < w; i++) {
			for(int j = 0; j < h; j++) {
				Point3D p = f.computePoint(new Point2D.Double(((double)i - tx) / sx, ((double)j - ty) / sy));
				double nsmooth = p.z + 1 - Math.log(Math.abs(Math.log((p.x * p.x) + (p.y * p.y))))/Math.log(2);
				g.setColor(co.getColor((nsmooth / (params.maxIter + 1))));
				//g.setColor(co.getColor(p.z));
				g.fillRect(i, j, 1, 1);
			}
		}

		return bi;
		
//		ByteArrayOutputStream baos = new ByteArrayOutputStream();
//		ImageIO.write(bi, "png", baos);
//		baos.flush();
//		context.write(key, new BytesWritable(baos.toByteArray()));
//		baos.close();
	}
}
